package pl.cba.solgar.game.rogal;

import java.util.Collections;
import java.util.LinkedList;
import java.util.ListIterator;

public class Timeline {
	private LinkedList<TimelineEntity> entities;
	private LinkedList<TimelineEntity> tiredEntities;
	ListIterator<TimelineEntity> iterator;
	private TimelineEntity currentEntity;

	boolean isCycleInProgress = false;

	public Timeline() {
		entities = new LinkedList<Timeline.TimelineEntity>();
		tiredEntities = new LinkedList<Timeline.TimelineEntity>();
	}

	public void register(TimelineEntity entity) {
		entities.add(entity);
	}

	public void unregister(TimelineEntity ent) {
		entities.remove(ent);
	}

	public void print() {
		System.out.println(entities);

		for (TimelineEntity entity : entities)
			System.out.println("entity: " + entity.baseSpeed);
	}

	public void runCycle() {
		if (isCycleInProgress)
			return;

		isCycleInProgress = true;
		for (TimelineEntity entity : entities)
			entity.increaseSpeedPointsPool();
		while (!entities.isEmpty())
			if (nextStep())
				return;
		endOfCycle();
	}

	public void continueCycle() {
		while (!entities.isEmpty())
			if (nextStep())
				return;
		endOfCycle();
		for (TimelineEntity entity : entities)
			System.out.println("entity " + entity.baseSpeed + "  moved times: " + entity.moved);
	}

	public void endOfCycle() {
		System.out.println("end of timeline cycle!");
		LinkedList<TimelineEntity> tmp = entities;
		entities = tiredEntities;
		tiredEntities = tmp;
		isCycleInProgress = false;
	}

	public boolean nextStep() {
		Collections.sort(entities, Collections.reverseOrder());
		currentEntity = entities.getFirst();
		if (currentEntity.actionInProgress != null) {
			if (currentEntity.speedPointsPool >= 0)
				currentEntity.actionInProgress.execute();
			else
				currentEntity.actionInProgress.progress();
			tiredEntities.add(entities.removeFirst());
		}
		// no action in progress
		else {
			if (currentEntity.speedPointsPool < currentEntity.getMaxCost()) {
				tiredEntities.add(entities.removeFirst());
				System.out.println("[timeline] rest: " + currentEntity.baseSpeed + "\towner.speedPoints: " + currentEntity.speedPointsPool);
			}
			else {
				if (currentEntity.isPlayer)
					return true;
				else
					doAction(null);
			}
		}
		return false;
	}

	public void doAction(TimelineAction action) {
		if (action == null)
			action = currentEntity.requestAction();
		currentEntity.speedPointsPool -= action.getTimeCost();
		if (currentEntity.speedPointsPool < currentEntity.getMaxCost()) {
			tiredEntities.add(entities.removeFirst());
		}
		if(action.immediate)
			action.execute();
		else
			tiredEntities.add(entities.removeFirst());
	}

	public void update() {
		currentEntity.requestAction();
	}

	public class TimelineEntity implements Comparable<TimelineEntity> {
		boolean isPlayer = false;
		Timeline timeline;
		private int baseSpeed;
		private int speedPointsPool;
		private TimelineAction actionInProgress;
		int moved = 0;

		public TimelineEntity(Timeline timeline, int bs) {
			baseSpeed = bs;
			speedPointsPool = 0;
			actionInProgress = null;
			this.timeline = timeline;
			if (bs == 128)
				isPlayer = true;
		}

		public TimelineAction requestAction() {
			return new TimelineAction(this);
		}

		public void increaseSpeedPointsPool() {
			speedPointsPool += baseSpeed;
		}

		public int getSpeedPointsPool() {
			return speedPointsPool;
		}

		public void depletePool(int byVal) {
			speedPointsPool -= byVal;
		}

		public int getBaseSpeed() {
			return baseSpeed;
		}

		public int getMaxCost() {
			return 100;
		}

		public void actionFinished() {
			actionInProgress = null;
		}

		public int compareTo(TimelineEntity o) {
			if (this.getSpeedPointsPool() > o.getSpeedPointsPool())
				return 1;
			else if (this.getSpeedPointsPool() < o.getSpeedPointsPool())
				return -1;
			else
				return 0;
		}

		public String toString() {
			return "" + getSpeedPointsPool();
		}

	}

	public class TimelineAction {

		boolean immediate = true;
		TimelineEntity owner;

		public TimelineAction(TimelineEntity owner) {
			this.owner = owner;
		}

		public void progress() {

		}

		public void execute() {
			owner.moved += 1;
			if (owner.baseSpeed == 128)
				System.out.println("[timeline] execute: " + owner.baseSpeed + "\tplayer like timeline entity");
			else
				System.out.println("[timeline] execute: " + owner.baseSpeed + "\towner.speedPoints: " + owner.speedPointsPool);
		}

		public int getTimeCost() {
			return 75;
		}
	}

}
